#include "Logueador.h"

Logueador::Logueador(Cliente* cli, VectorSala& vec, ArchivoUsuarios& arch)
:vecSalas(vec), archUsuarios(arch)
{
	cliente = cli;
	estaCorriendo = false;
}

void Logueador::startMethod()
{
	estaCorriendo = true;
	Usuario usuario;
	bool seLogueo = logear(usuario);
	if(seLogueo && estaCorriendo){
		cliente->asignarUsuario(usuario);
		agregarASala();
	}
}

bool Logueador::logear(Usuario& user)
{
	Json::Value root;
	std::string opcion;

	do{
		cliente->recibir(root);
		opcion = root.get("Opcion", "").asString();

		if(opcion == "Iniciar sesion"){
			if(iniciarSesion(user, root))
				return true;
		}else{
			if(opcion == "Crear cuenta"){
				if(crearCuenta(user, root))
					return true;
			}
		}
	}while(estaCorriendo && cliente->estaConectado());

	return false;
}

bool Logueador::iniciarSesion(Usuario& user, const Json::Value& root)
{
	std::string nombreDeUsuario = root.get("Nombre de usuario","").asString();
	std::string contrasenia = root.get("Contrasenia","").asString();

	Json::Value respuesta;
	if(archUsuarios.autenticar(nombreDeUsuario, contrasenia)){
		respuesta["Respuesta"] = "Ingreso exitoso";
		cliente->enviar(respuesta);
		archUsuarios.obtenerUsuario(user, nombreDeUsuario);
		return true;
	}else{
		respuesta["Respuesta"] = "Usuario o contrasena incorrecta";
		cliente->enviar(respuesta);
		return false;
	}
}

bool Logueador::crearCuenta(Usuario& user, const Json::Value& root)
{
	std::string nombreDeUsuario = root.get("Nombre de usuario","").asString();

	Json::Value respuesta;
	if(!archUsuarios.existeUsuario(nombreDeUsuario)){
		respuesta["Respuesta"] = "Usuario disponible";
		cliente->enviar(respuesta);

		Json::Value rootContrasenia;
		cliente->recibir(rootContrasenia);
		std::string contrasenia = rootContrasenia.get("Contrasenia","").asString();

		if(archUsuarios.crearUsuario(nombreDeUsuario, contrasenia)){
			archUsuarios.obtenerUsuario(user, nombreDeUsuario);
			return true;
		}else
			return false;
	}else{
		respuesta["Respuesta"] = "Usuario no disponible";
		cliente->enviar(respuesta);
		return false;
	}
}

void Logueador::matar()
{
	estaCorriendo = false;
	cliente->dejarDeEnviarYRecibir();
}

void Logueador::agregarASala()
{
	bool seAgregoAUnaSala = false;
	do{
		Json::Value root;
		cliente->recibir(root);
		std::string eleccion = root.get("eleccion","").asString();

		if(eleccion == "Actualizar salas"){
			cliente->enviar(vecSalas.getJson());
		}else{
			if(eleccion == "Seleccionar sala"){
				seAgregoAUnaSala = seleccionarSala(root);
			}else{
				if(eleccion == "Crear sala"){
					seAgregoAUnaSala = crearSala(root);
				}
			}
		}
	}while(!seAgregoAUnaSala && estaCorriendo && cliente->estaConectado());
}

bool Logueador::seleccionarSala(const Json::Value& root)
{
	bool seAgregoAUnaSala = false;
	Json::Value respuesta;

	unsigned numeroDeSala = root.get("Numero de sala", 0).asUInt();
	if(numeroDeSala <= vecSalas.size() && numeroDeSala != 0){

		unsigned nivelSala = vecSalas[numeroDeSala-1]->getNivel();
		if(nivelSala <= cliente->getMaxNivelAlcanzado()){

			seAgregoAUnaSala = vecSalas[numeroDeSala-1]->agregarJugador(cliente);
			if(seAgregoAUnaSala)
				respuesta["Respuesta"] = "Ingreso exitoso a sala";
			else
				respuesta["Respuesta"] = "Sala llena";
		}

		else{
			respuesta["Respuesta"] = "No puede acceder a ese nivel";
		}

	}
	else{
		respuesta["Respuesta"] = "Numero sala incorrecto";
	}
	cliente->enviar(respuesta);

	return seAgregoAUnaSala;
}

bool Logueador::crearSala(const Json::Value& root)
{
	bool seAgregoAUnaSala = false;
	Json::Value respuesta;
	unsigned nivelElegido = root.get("Nivel", 0).asUInt();
	if(nivelElegido <= cliente->getMaxNivelAlcanzado() && nivelElegido > 0){

		unsigned cantJugadores = root.get("Cantidad de jugadores", 0).asUInt();
		unsigned cantJugadoresMaxDelNivel = getMaximoJugadoresNivel(nivelElegido);
		if((cantJugadores > 1) && (cantJugadores <= cantJugadoresMaxDelNivel)){
			Sala* sala = new Sala(cantJugadores, nivelElegido, archUsuarios);
			sala->agregarJugador(cliente);
			vecSalas.pushBack(sala);
			respuesta["Respuesta"] = "Ingreso exitoso a sala";
			seAgregoAUnaSala = true;
		}else{
			respuesta["Respuesta"] = "Cantidad de jugadores erronea";
		}

	}
	else {
		respuesta["Respuesta"] = "Numero de nivel incorrecto";
	}
	cliente->enviar(respuesta);

	return seAgregoAUnaSala;
}


unsigned Logueador::getMaximoJugadoresNivel(const unsigned& nivelElegido)
{
	CargaJson levantador;
	Json::Value root;
	std::stringstream s;
	s << "nivel_" << nivelElegido << ".json";
	std::string sNivel = s.str();
	levantador.getJson(sNivel,root);

	return root["maxJugadores"].asUInt();
}
